package com.zzq.service.impl;

import cn.hutool.core.io.FileUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.oss.model.PartETag;
import com.aliyuncs.exceptions.ClientException;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zzq.enumerate.OssPathEnum;
import com.zzq.enumerate.RedisKeyEnum;
import com.zzq.enumerate.UploadStatusEnum;
import com.zzq.exception.PhoneException;
import com.zzq.result.SmileResult;
import com.zzq.domain.dto.SmileAlbumDTO;
import com.zzq.domain.entity.SmileAlbum;
import com.zzq.domain.entity.SmileAlbumPhoto;
import com.zzq.domain.entity.SmilePhoto;
import com.zzq.security.util.UserUtil;
import com.zzq.service.*;
import com.zzq.util.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import static com.zzq.enumerate.RedisKeyEnum.SMILE_MEITU_MSGS_ALBUM;
import static com.zzq.enumerate.RedisKeyEnum.SMILE_PRICEPHOTO_UPLOAD;

@Service
@Slf4j
public class AlbumServiceImpl implements AlbumService {

    @Autowired
    SmileAlbumService smileAlbumService;

    @Autowired
    SmilePhotoService smilePhotoService;

    @Autowired
    SmileAlbumPhotoService smileAlbumPhotoService;

    @Autowired
    SmileShootRecordService shootRecordService;

    @Autowired
    OssFileUtil ossFileUtil;

    @Autowired
    private RedisCache redisCache;


    @Value("${meitu.request_url}")
    private String request_url;
    @Value("${meitu.api_key}")
    private String api_key;
    @Value("${meitu.api_secret}")
    private String api_secret;
    @Value("${meitu.media_code}")
    private String media_code;
    @Value("${meitu.query_url}")
    private String query_url;
    @Value("${meitu.repost_url}")
    private String repost_url;

    private Map<String, Lock> albumLocks = new ConcurrentHashMap<>();


    @Override
    public SmileResult getUploadId(Long albumId,String filetype) {
        Long userID = UserUtil.getUserID();

        String fileName=UUIDUtil.getUUID()+filetype;
        String uploadId = ossFileUtil.getUploadId(OssPathEnum.CLIENT_MASTER.getPath(albumId+""), fileName);
        String allUrl=OssPathEnum.CLIENT_MASTER.getPath(albumId+"")+fileName;


        SmilePhoto smilePhoto = new SmilePhoto();
        smilePhoto.setPhotographerId(userID);
        smilePhoto.setPhotoTime(new Date());
        smilePhoto.setPhotoDir(allUrl);
        smilePhoto.setUploadStatus(UploadStatusEnum.UPLOADING.getName());
        smilePhotoService.save(smilePhoto);
        Long id = smilePhoto.getId();

        HashMap<String,String> hashMap=new HashMap<>();
        hashMap.put("uploadId",uploadId);
        hashMap.put("photoId",String.valueOf(id));
        hashMap.put("allUrl",allUrl);

        System.err.println(JSON.toJSONString(hashMap));


        return SmileResult.sucess("获取uploadId,fileName,photoId成功",hashMap);
    }

    @Override
    @Transactional
    public SmileResult addAlbumPhoto(SmileAlbumDTO albumDTO) {
        Long userID = UserUtil.getUserID();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());

        // 将时间部分设置为0点
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);

        // 获取当天凌晨0点的 Date 对象
        Date midnight = calendar.getTime();
        //保存相册信息
        SmileAlbum album = BeanCopyUtils.copyBean(albumDTO, SmileAlbum.class);
        LambdaQueryWrapper<SmileAlbum> smileAlbumWrapper = new LambdaQueryWrapper<>();
        smileAlbumWrapper.eq(SmileAlbum::getAlbumName, album.getAlbumName())
                .eq(SmileAlbum::getClientNo, album.getClientNo())
                .eq(SmileAlbum::getPhotographerId,userID);
        smileAlbumWrapper.between(SmileAlbum::getCreatedTime, midnight, new Date(midnight.getTime() + 86400000));
        SmileAlbum one = smileAlbumService.getOne(smileAlbumWrapper);
        if (one != null) {
            return SmileResult.sucess("相册已创建", one);
        } else {
            album.setPhotographerId(userID);
            smileAlbumService.save(album);
            return SmileResult.sucess("相册创建成功", album);
        }

    }

    @Override
    public SmileResult albumList() {
        return null;
    }



    @Override
    public SmileResult addOnePhoto(SmilePhoto smilePhoto , Long albumId) {
        log.info("完成分片，添加相片");
        try {

            String fileUrl = ossFileUtil.getFileUrl(smilePhoto.getPhotoDir());

            addMeiTuTask(fileUrl, String.valueOf(albumId), smilePhoto.getId() + "");

            getMeiTuTask(String.valueOf(albumId));
            //保存拍摄关系
            Long photoId = smilePhoto.getId();
            SmileAlbumPhoto smileAlbumPhoto = new SmileAlbumPhoto();
            smileAlbumPhoto.setAlbumId(albumId);
            smileAlbumPhoto.setPhotoId(photoId);
            smileAlbumPhotoService.save(smileAlbumPhoto);
        } catch (IOException e) {
            return SmileResult.error("图片上传异常");
        } catch (ClientException e) {

            return SmileResult.error("oss异常");
        }
        return SmileResult.sucess("上传完成");
    }

    @Override
    public SmileResult uploadPricePhoto( MultipartFile file,
                                         Integer chunkIndex,
                                         Integer totalChunks,
                                         Long albumId,
                                         String uploadId,
                                         Long photoId,
                                         String allUrl) throws IOException {

        String photoDir = allUrl;
        if (chunkIndex<=totalChunks) {
            PartETag partETag = ossFileUtil.initiateMultipartUpload(file, photoDir, chunkIndex, uploadId);
            ArrayList<String> partETags = new ArrayList<>();
            partETags.add(JSON.toJSONString(partETag));
            redisCache.setCacheList(SMILE_PRICEPHOTO_UPLOAD.key(uploadId),partETags);
            if (chunkIndex<totalChunks){
                return     SmileResult.sucess("上传成功,继续上传");
            }
        }
        if (chunkIndex==totalChunks){
            List<String> cacheList = redisCache.getCacheList(SMILE_PRICEPHOTO_UPLOAD.key(uploadId));
            redisCache.deleteObject(SMILE_PRICEPHOTO_UPLOAD.key(uploadId));
            ArrayList<PartETag> partETags=new ArrayList();
            for (String s : cacheList) {
                PartETag partETag = JSON.parseObject(s, PartETag.class);
                partETags.add(partETag);
            }

            ossFileUtil.craftPhoto(photoDir,partETags,uploadId);
            SmilePhoto photo = smilePhotoService.getById(photoId);
            photo.setUploadStatus(UploadStatusEnum.UPLOADING.getName());
            addOnePhoto(photo,albumId);
            return  SmileResult.sucess("上传成功");
        }
        return SmileResult.waring("上传失败");
    }


    public void addMeiTuTask(String picUrl, String albumId, String photoId) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("api_key", api_key);
        jsonObject.put("api_secret", api_secret);
        jsonObject.put("media_code", media_code);
        jsonObject.put("media_data", picUrl);
        jsonObject.put("repost_url", repost_url);
        //上传数据
        String json = HttpUtil.createPost(request_url)
                .header("content-type", "application/json").body(jsonObject.toString()).execute().body();
        JSONObject res = JSON.parseObject(json);

        //判断状态
        Integer code = (Integer) res.get("code");
        if (code==0) {
            JSONObject data = JSON.parseObject(res.get("data").toString());
            String msgId = (String) data.get("msg_id");
            //将相册id作为key msg 作为集合 value
            redisCache.setCacheMapValue(SMILE_MEITU_MSGS_ALBUM.key(albumId), photoId, msgId);
        } else {
            throw new PhoneException("修图失败");
        }
    }



    //获取美图任务
    @Async
    public     void getMeiTuTask(String albumId) throws IOException, ClientException {
        Lock lock = albumLocks.computeIfAbsent(albumId, k -> new ReentrantLock());
        lock.lock(); // 获取针对 albumId 的锁

        try {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("api_key", api_key);
            jsonObject.put("api_secret", api_secret);
            String reidsKey = SMILE_MEITU_MSGS_ALBUM.key(albumId);
            if (redisCache.isEmptyMap(reidsKey)) {
                return;
            }
            while (!redisCache.isEmptyMap(reidsKey)) {
                //获取Map
                Map<String, Object> cacheMap = redisCache.getCacheMap(reidsKey);
                String hkey = null;
                Iterator<String> hkeys = cacheMap.keySet().iterator();
                //遍历hkeys
                while (hkeys.hasNext()) {
                    if (hkey == null) {
                        hkey = hkeys.next();
                    }
                    String msg_id = (String) cacheMap.get(hkey);
                    jsonObject.put("msg_id", msg_id);
                    String json = HttpUtil.createPost(query_url)
                            .header("content-type", "application/json").body(jsonObject.toString()).execute().body();
                    JSONObject res = JSON.parseObject(json);
                    Integer code = (Integer) res.get("code");
                    if (code==0) {
                        log.info("执行线程");
                        long threadId = Thread.currentThread().getId();
                        log.info("当前线程的ID：{}" , threadId);
                        log.info("当前线程的PhotoId：{}" , hkey);
                        redisCache.delCacheMapValue(reidsKey, hkey);
                        JSONObject data = JSON.parseObject(res.get("data").toString());
                        //将图片上传到oss上
                        String url = (String) data.get("media_data");
                        File tempFile = FileUtil.file("temp_image.jpg");
                        FileUtil.writeFromStream(new URL(url).openStream(), tempFile);
                        MultipartFile multipartFile = ImageUtil.convertFileToMultipartFile(tempFile);
                        String metuDir = ossFileUtil.uploadFile(multipartFile, OssPathEnum.CLIENT_MEITU.getPath(albumId+""), hkey);
                        MultipartFile waterMarkFile = ImageUtil.setWaterMark(multipartFile, hkey);
                        String waterDir = ossFileUtil.uploadStaticFile(waterMarkFile, OssPathEnum.CLIENT_MASTER_WATERMARK.getPath(albumId + ""), hkey);
                        String waterAllUrl = ossFileUtil.getStaticFileUrl(waterDir);

                        SmilePhoto smilePhoto = new SmilePhoto();
                        smilePhoto.setId(Long.valueOf(hkey));
                        smilePhoto.setPhotoWatermarkUrl(waterAllUrl);
                        smilePhoto.setPhotoMetuDir(metuDir);
                        smilePhoto.setUploadStatus(UploadStatusEnum.FINISH.getName());
                        smilePhotoService.updateById(smilePhoto);
                        //消除hkey
                        hkey = null;
                    } else {
                        log.info("执行等待");
                        long threadId = Thread.currentThread().getId();
                        log.info("当前线程的ID：{}" , threadId);
                        log.info("当前线程的PhotoId：{}" , hkey);
                        try {
                            Thread.sleep(1000); // 如果图片尚未生成 停1秒
                        } catch (InterruptedException e) {
                            Thread.currentThread().interrupt();
                        }
                    }
                }
            }
        } finally {
            lock.unlock(); // 释放锁
        }

    }

}
